package zdc.media {
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.StageVideoAvailabilityEvent;
import flash.geom.Rectangle;
import flash.media.StageVideo;
import flash.media.StageVideoAvailability;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

import zdc.Util;

/**
 *
 * @author Simple Slime
 */
public class OmniVideo extends Sprite {
    //视频开始
    public static const VIDEO_START:String = "OmniVideo_VIDEO_START";
    //视频结束
    public static const VIDEO_END:String = "OmniVideo_VIDEO_END";
    //视频不存在
    public static const VIDEO_NOT_FOUND:String = "OmniVideo_VIDEO_NOT_FOUND";
    //自动检测
    public static const AUTO_DETECT:int = 0;
    //强制软解码
    public static const FORCE_SOFT:int = 1;
    //强制硬解码
    public static const FORCE_HARD:int = 2;
    //播放方式
    private var playType:int = AUTO_DETECT;

    //位置，高宽
    private var bounding:Rectangle;

    private var _playing:Boolean = false;
    private var path:String = "";
    private var accel:Boolean = false;
    private var ns:NetStream;
    private var nc:NetConnection;
    private var softVid:Video;
    private var hardVid:StageVideo;

    private var waitingForPlay:Boolean = false;
    private var autoScale:Boolean = true;

    //计算舞台变化
    private var lastSw:Number, lastSh:Number;

    public function OmniVideo(path:String = "", bounding:Rectangle = null, playType:int = AUTO_DETECT) {
        this.path = path;
        this.bounding = bounding;
        this.playType = playType;

        initPreVars();

        stage ? init() : addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function init(e:Event = null):void {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        initPostVars();
        initStates();
        initEvents();
        run();
    }

    private function initPreVars():void {

    }

    private function initPostVars():void {

    }

    private function initStates():void {
        bounding ||= new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
        lastSw = stage.stageWidth;
        lastSh = stage.stageHeight;

        drawSpace();
    }

    private function initEvents():void {
        stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onCheckStageVideo);
        stage.addEventListener(Event.RESIZE, onStageResize);
        this.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
    }

    //舞台尺寸更改的时候更改视频尺寸
    private function onStageResize(e:Event):void {
        if (!softVid && !hardVid) {
            return;
        }

        var scalex:Number = stage.stageWidth / lastSw;
        var scaley:Number = stage.stageHeight / lastSh;

        if (softVid) {
            softVid.width *= scalex;
            softVid.height *= scaley;
        }

        lastSw = stage.stageWidth;
        lastSh = stage.stageHeight;
    }

    private function run():void {

    }

    private function onRemoved(e:Event):void {
        this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
        stage.removeEventListener(Event.RESIZE, onStageResize);
        dispose();
    }

    /**
     * 绘制透明填充区域
     */
    private function drawSpace():void {
        var g:Graphics = this.graphics;
        g.beginFill(0, 0);
        g.drawRect(0, 0, bounding.width, bounding.height);
        g.endFill();
        this.x = bounding.x;
        this.y = bounding.y;
    }

    //检测硬解码支持
    private function onCheckStageVideo(e:StageVideoAvailabilityEvent):void {
        stage.removeEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onCheckStageVideo);
        accel = e.availability == StageVideoAvailability.AVAILABLE;

        //硬解码
        if (playType == FORCE_HARD || accel) {
            if (hardVid == null) {
                hardVid = stage.stageVideos[0];
                hardVid.viewPort = bounding;

                createNet();
            }
        }
        //软解码
        else {
            if (softVid == null) {
                softVid = new Video(bounding.width, bounding.height);
                addChild(softVid);

                createNet();
            }
        }

    }

    //创建网络对象
    private function createNet():void {
        nc = new NetConnection();
        nc.connect(null);
        ns = new NetStream(nc);
        ns.client = this;
        ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsynErr);
        ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

        if (hardVid) {
            hardVid.attachNetStream(ns);
        }
        else if (softVid) {
            softVid.attachNetStream(ns);
        }

        if (waitingForPlay) {
            play();
        }
    }

    /**
     * 播放
     */
    public function play(path:String = ""):void {
        if (path == "" && this.path == "") {
            return;
        }

        this.path = path == "" ? this.path : path;

        //如果还没有实例化视频对象，则先设置等待播放标识
        if (ns && (softVid || hardVid)) {
            ns.play(this.path);
            _playing = true;
            waitingForPlay = false;
        }
        else {
            waitingForPlay = true;
            _playing = false;
        }

        //trace("lets go!", ns, softVid, hardVid, waitingForPlay);
    }

    /**
     *
     * @param    e
     */
    protected function onNetStatus(e:NetStatusEvent):void {
        //trace("e.info.code:", e.info.code);
        switch (e.info.code) {
            case "NetStream.Play.Stop":
                dispatchEvent(new Event(VIDEO_END));
                _playing = false;
                break;
            case "NetStream.Play.Start":
                dispatchEvent(new Event(VIDEO_START));
                _playing = true;
                break;
            case "NetStream.Play.StreamNotFound":
                dispatchEvent(new Event(VIDEO_NOT_FOUND));
                trace("StreamNotFound:", path)
                _playing = false;
                break;
        }
    }

    /**
     * 暂停
     */
    public function pause():void {
        ns.pause();
    }

    /**
     * 暂停播放并回到起点位置
     */
    public function stop():void {
        ns.pause();
        ns.seek(0);
    }

    /**
     * 销毁
     */
    public function dispose():void {
        if (nc) {
            nc.close();
            nc = null;
        }
        if (ns) {
            ns.pause();
            ns.close();
            ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsynErr);
            ns.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
            ns = null;
        }

        if (softVid) {
            softVid.attachNetStream(null);
            softVid = null;
        }
        else if (hardVid) {
            hardVid.attachNetStream(null);
            hardVid = null;
        }
    }

    private function onAsynErr(e:AsyncErrorEvent):void {

    }

    public function onMetaData(evt:Object):void {

    }

    public function onXMPData(info:Object):void {

    }

    public function onPlayStatus(info:Object):void {
        //trace("onPlayStatus", info.code);
    }

    /**
     * 是否正在播放
     */
    public function get playing():Boolean {
        return _playing;
    }

    /**
     * 硬件加速
     */
    public function get accelerating():Boolean {
        return accel;
    }

    /**
     * 是否让视频随着舞台改变尺寸
     */
    public function get enableAutoScale():Boolean {
        return autoScale;
    }
}

}